Files
android_external_libcxx/test/libcxx/input.output/filesystems/convert_file_time.sh.cpp
Eric Fiselier a0866c5fb5 Implement <filesystem>
This patch implements the <filesystem> header and uses that
to provide <experimental/filesystem>.

Unlike other standard headers, the symbols needed for <filesystem>
have not yet been placed in libc++.so. Instead they live in the
new libc++fs.a library. Users of filesystem are required to link this
library. (Also note that libc++experimental no longer contains the
definition of <experimental/filesystem>, which now requires linking libc++fs).

The reason for keeping <filesystem> out of the dylib for now is that
it's still somewhat experimental, and the possibility of requiring an
ABI breaking change is very real. In the future the symbols will likely
be moved into the dylib, or the dylib will be made to link libc++fs automagically).

Note that moving the symbols out of libc++experimental may break user builds
until they update to -lc++fs. This should be OK, because the experimental
library provides no stability guarantees. However, I plan on looking into
ways we can force libc++experimental to automagically link libc++fs.

In order to use a single implementation and set of tests for <filesystem>, it
has been placed in a special `__fs` namespace. This namespace is inline in
C++17 onward, but not before that. As such implementation is available
in C++11 onward, but no filesystem namespace is present "directly", and
as such name conflicts shouldn't occur in C++11 or C++14.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338093 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-27 03:07:09 +00:00

308 lines
10 KiB
C++

//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11
// <filesystem>
// typedef TrivialClock file_time_type;
// RUN: %build -I%libcxx_src_root/src/filesystem
// RUN: %run
#include <filesystem>
#include <chrono>
#include <type_traits>
#include <limits>
#include <cstddef>
#include <cassert>
#include "filesystem_common.h"
#ifndef __SIZEOF_INT128__
#define TEST_HAS_NO_INT128_T
#endif
using namespace std::chrono;
namespace fs = std::__fs::filesystem;
using fs::file_time_type;
using fs::detail::time_util;
#ifdef TEST_HAS_NO_INT128_T
static_assert(sizeof(fs::file_time_type::rep) <= 8, "");
#endif
enum TestKind { TK_128Bit, TK_64Bit, TK_32Bit, TK_FloatingPoint };
template <class TimeT>
constexpr TestKind getTimeTTestKind() {
if (sizeof(TimeT) == 8 && !std::is_floating_point<TimeT>::value)
return TK_64Bit;
else if (sizeof(TimeT) == 4 && !std::is_floating_point<TimeT>::value)
return TK_32Bit;
else if (std::is_floating_point<TimeT>::value)
return TK_FloatingPoint;
else
assert(false && "test kind not supported");
}
template <class FileTimeT>
constexpr TestKind getFileTimeTestKind() {
using Rep = typename FileTimeT::rep;
if (std::is_floating_point<Rep>::value)
return TK_FloatingPoint;
else if (sizeof(Rep) == 16)
return TK_128Bit;
else if (sizeof(Rep) == 8)
return TK_64Bit;
else
assert(false && "test kind not supported");
}
template <class FileTimeT, class TimeT, class TimeSpecT,
class Base = time_util<FileTimeT, TimeT, TimeSpecT>,
TestKind = getTimeTTestKind<TimeT>(),
TestKind = getFileTimeTestKind<FileTimeT>()>
struct test_case;
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit>
: public Base {
using Base::convert_from_timespec;
using Base::convert_to_timespec;
using Base::is_representable;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
static constexpr bool test_timespec() {
static_assert(is_representable(TimeSpecT{max_time_t, 0}), "");
static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
static_assert(is_representable(TimeSpecT{max_time_t, max_nsec}), "");
static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
static_assert(is_representable(TimeSpecT{min_time_t, 999999999}), "");
static_assert(is_representable(TimeSpecT{min_time_t, 1000000000}), "");
static_assert(is_representable(TimeSpecT{min_time_t, min_nsec_timespec}),
"");
return true;
}
static constexpr bool test_file_time_type() {
// This kinda sucks. Oh well.
static_assert(!Base::is_representable(FileTimeT::max()), "");
static_assert(!Base::is_representable(FileTimeT::min()), "");
return true;
}
static constexpr bool check_round_trip(TimeSpecT orig) {
TimeSpecT new_ts = {};
FileTimeT out = convert_from_timespec(orig);
assert(convert_to_timespec(new_ts, out));
return new_ts.tv_sec == orig.tv_sec && new_ts.tv_nsec == orig.tv_nsec;
}
static constexpr bool test_convert_timespec() {
static_assert(check_round_trip({0, 0}), "");
static_assert(check_round_trip({0, 1}), "");
static_assert(check_round_trip({1, 1}), "");
static_assert(check_round_trip({-1, 1}), "");
static_assert(check_round_trip({max_time_t, max_nsec}), "");
static_assert(check_round_trip({max_time_t, 123}), "");
static_assert(check_round_trip({min_time_t, min_nsec_timespec}), "");
static_assert(check_round_trip({min_time_t, 123}), "");
return true;
}
static bool test() {
static_assert(test_timespec(), "");
static_assert(test_file_time_type(), "");
static_assert(test_convert_timespec(), "");
return true;
}
};
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_128Bit>
: public test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit> {
};
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_64Bit>
: public Base {
using Base::convert_from_timespec;
using Base::is_representable;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
static constexpr bool test_timespec() {
static_assert(is_representable(TimeSpecT{max_seconds, max_nsec}), "");
static_assert(!is_representable(TimeSpecT{max_seconds + 1, 0}), "");
static_assert(!is_representable(TimeSpecT{max_seconds, max_nsec + 1}), "");
static_assert(!is_representable(TimeSpecT{max_time_t, 0}), "");
static_assert(is_representable(TimeSpecT{min_seconds, 0}), "");
static_assert(
is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec}), "");
static_assert(
is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}),
"");
static_assert(
!is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec - 1}),
"");
static_assert(!is_representable(TimeSpecT{min_time_t, 999999999}), "");
return true;
}
static constexpr bool test_file_time_type() {
static_assert(Base::is_representable(FileTimeT::max()), "");
static_assert(Base::is_representable(FileTimeT::min()), "");
return true;
}
static constexpr bool test_convert_timespec() {
static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec}) ==
FileTimeT::max(),
"");
static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec - 1}) <
FileTimeT::max(),
"");
static_assert(convert_from_timespec(TimeSpecT{max_seconds - 1, 999999999}) <
FileTimeT::max(),
"");
static_assert(convert_from_timespec(TimeSpecT{
min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(),
"");
static_assert(convert_from_timespec(
TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) >
FileTimeT::min(),
"");
static_assert(convert_from_timespec(TimeSpecT{min_seconds, 0}) >
FileTimeT::min(),
"");
return true;
}
static bool test() {
static_assert(test_timespec(), "");
static_assert(test_file_time_type(), "");
static_assert(test_convert_timespec(), "");
return true;
}
};
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_64Bit>
: public Base {
static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
using Base::convert_from_timespec;
using Base::is_representable;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
static constexpr bool test_timespec() {
static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
return true;
}
static constexpr bool test_file_time_type() {
static_assert(!is_representable(FileTimeT::max()), "");
static_assert(!is_representable(FileTimeT::min()), "");
static_assert(is_representable(FileTimeT(seconds(max_time_t))), "");
static_assert(is_representable(FileTimeT(seconds(min_time_t))), "");
return true;
}
static constexpr bool test_convert_timespec() {
// FIXME add tests for 32 bit builds
return true;
}
static bool test() {
static_assert(test_timespec(), "");
static_assert(test_file_time_type(), "");
static_assert(test_convert_timespec(), "");
return true;
}
};
template <class FileTimeT, class TimeT, class TimeSpec, class Base,
TestKind FileTimeTKind>
struct test_case<FileTimeT, TimeT, TimeSpec, Base, TK_FloatingPoint,
FileTimeTKind> : public Base {
static bool test() { return true; }
};
template <class TimeT, class NSecT = long>
struct TestTimeSpec {
TimeT tv_sec;
NSecT tv_nsec;
};
template <class Dur>
struct TestClock {
typedef Dur duration;
typedef typename duration::rep rep;
typedef typename duration::period period;
typedef std::chrono::time_point<TestClock> time_point;
static constexpr const bool is_steady = false;
static time_point now() noexcept { return {}; }
};
template <class IntType, class Period = std::micro>
using TestFileTimeT = time_point<TestClock<duration<IntType, Period> > >;
int main() {
{ assert((test_case<file_time_type, time_t, struct timespec>::test())); }
{
assert((test_case<TestFileTimeT<int64_t>, int64_t,
TestTimeSpec<int64_t, long> >::test()));
}
{
assert((test_case<TestFileTimeT<long long>, int32_t,
TestTimeSpec<int32_t, int32_t> >::test()));
}
{
// Test that insane platforms like ppc64 linux, which use long double as time_t,
// at least compile.
assert((test_case<TestFileTimeT<long double>, double,
TestTimeSpec<long double, long> >::test()));
}
#ifndef TEST_HAS_NO_INT128_T
{
assert((test_case<TestFileTimeT<__int128_t, std::nano>, int64_t,
TestTimeSpec<int64_t, long> >::test()));
}
{
assert((test_case<TestFileTimeT<__int128_t, std::nano>, int32_t,
TestTimeSpec<int32_t, int32_t> >::test()));
}
#endif
}